package com.gitee.huanminabc.jcommon.base;



import com.gitee.huanminabc.jcommon.exception.CommonException;
import com.gitee.huanminabc.jcommon.file.FileWriterUtil;
import com.gitee.huanminabc.jcommon.file.ReadFileBytesUtil;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Map;

/**
 * 序列化工具类
 */
public class SerializeUtil {
    public static byte[] serialize(Object object) {
        if (object == null) {
            throw new CommonException("序列化对象不能为空");
        }
        if (object instanceof Serializable){
            ObjectOutputStream oos = null;
            ByteArrayOutputStream baos = null;
            try {
                // 序列化
                baos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(baos);
                oos.writeObject(object);
                byte[] bytes = baos.toByteArray();
                return bytes;
            } catch (Exception e) {
                throw new CommonException(e);
            }
        }
        throw new CommonException("{}对象不可序列化,请实现Serializable接口",object.getClass().getName());
    }

    public static void serializeToFile(Object object, File read) {
        byte[] serialize = serialize(object);
        FileWriterUtil.writeByteToFile(serialize, read, false);
    }

    public static <T> T deserialize(byte[] bytes, Class<T> tClass) {
        if (bytes == null || bytes.length == 0) {
            throw new CommonException("反序列化bytes不能为空");
        }
       //获取类是否实现了Serializable接口
        if (!Serializable.class.isAssignableFrom(tClass)){
            throw new CommonException("{}对象不可序列化,请实现Serializable接口",tClass.getName());
        }
        Class<?> aClass = areAllInnerClassesSerializable(tClass);
        if (aClass != null) {
            throw new CommonException("{}的内部类{}必须实现Serializable接口", tClass.getName(), aClass.getName());
        }

        ByteArrayInputStream bais = null;
        try {
            // 反序列化
            bais = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bais);
            return (T) ois.readObject();
        } catch (Exception e) {
           throw new CommonException(e);

        }
    }

    public static <T> T fileToDeserialize(File read, Class<T> tClass) {
        byte[] bytes = ReadFileBytesUtil.readByte(read);
        return deserialize(bytes, tClass);

    }


    // 检查成员使用了内部类, 并且内部类都实现了Serializable接口,如果没有实现Serializable接口,那么就返回这个类
    // 有一个缺陷,就是如果成员使用的是其他类内部的内部类,那么这里就没有继续深入处理,在序列化的时候,编译器会报错
    public static Class<?> areAllInnerClassesSerializable(Class<?> outerClass) {
        Class<?>[] declaredClasses = outerClass.getDeclaredClasses();
        //将数据结构转换为Map<String, Class<?>>
        Map<String, Class<?>> map = Arrays.stream(declaredClasses)
                .collect(java.util.stream.Collectors.toMap(Class::getName, clazz -> clazz));

        Field[] declaredFields = outerClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            if (declaredField.getType().isMemberClass() &&
                    !Modifier.isStatic(declaredField.getModifiers()) &&
                    !Modifier.isTransient(declaredField.getModifiers())) {
                Class<?> clazz = map.get(declaredField.getType().getName());
                if (clazz != null) {
                    //如果没有实现Serializable接口,那么就返回这个类
                    if (!Serializable.class.isAssignableFrom(clazz)) {
                        return clazz;
                    }
                }
            }
        }
        return null;
    }


}

